package com.grandpa;

import cn.hutool.core.util.StrUtil;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.Date;
import java.util.Map;
import java.util.Optional;

/**
 * @author tmf
 * @description:
 * @date 2024-11-20
 */

public class QuartzUtil {
    public static Scheduler SCHEDULER;

    private static final String DEFAULT_GROUP_NAME = "default";

    public static void init() throws SchedulerException {
        SCHEDULER = StdSchedulerFactory.getDefaultScheduler();
        SCHEDULER.start();

    }

    public static void shutdown() throws SchedulerException {
        SCHEDULER.shutdown();
    }

    public static void addJob(String name, Map<String, Object> params,Trigger trigger, Class<? extends Job> jobClass) throws SchedulerException {
        addJob(name, DEFAULT_GROUP_NAME, params, trigger, jobClass);
    }
    public static void addJob(String name, String group, Map<String, Object> params,Trigger trigger, Class<? extends Job> jobClass) throws SchedulerException {
        JobDetail jobDetail = buildJobDetail(name, group, params, jobClass);
        SCHEDULER.scheduleJob(jobDetail, trigger);
    }

    public static void addOnceJob(String name, Map<String, Object> params, long timestamp,  Class<? extends Job> jobClass) {
        addOnceJob(name, DEFAULT_GROUP_NAME, params, timestamp, jobClass);
    }
    public static void addOnceJob(String name, String group, Map<String, Object> params, long timestamp,  Class<? extends Job> jobClass) {
        try {
            JobDetail jobDetail = buildJobDetail(name, group, params, jobClass);
            long nowTime = System.currentTimeMillis();

            if(timestamp < nowTime) {
                Trigger trigger = TriggerBuilder.newTrigger()
                        .withIdentity(name, group)
                        .startNow()
                        .forJob(jobDetail)
                        .withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(0))
                        .build();
                SCHEDULER.scheduleJob(jobDetail, trigger);
                return;
            }

            Date futureRunTime = new Date(timestamp);
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(name, group)
                    .startAt(futureRunTime)
                    .forJob(jobDetail)
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(0))
                    .build();

            SCHEDULER.scheduleJob(jobDetail, trigger);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public static void addCronJob(String name, Map<String, Object> params, String cronStr, Class<? extends Job> jobClass) {
        addCronJob(name, DEFAULT_GROUP_NAME, params, cronStr, jobClass);
    }
    public static void addCronJob(String name, String group, Map<String, Object> params, String cronStr,Class<? extends Job> jobClass){
        try {
            JobDetail jobDetail = buildJobDetail(name, group, params, jobClass);

            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(name, group)
                    .withSchedule(CronScheduleBuilder.cronSchedule(cronStr))
                    .forJob(jobDetail)
                    .build();

            SCHEDULER.scheduleJob(jobDetail, trigger);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public static void deleteJob(String name) {
        deleteJob(name, DEFAULT_GROUP_NAME);
    }

    public static void deleteJob(String name, String group){
        try {
            System.out.println("JOB STOP:" + name);
            JobKey jobKey = new JobKey(name, group);

            SCHEDULER.interrupt(jobKey);
            SCHEDULER.deleteJob(jobKey);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private static JobDetail buildJobDetail(String name, String group, Map<String, Object> params, Class<? extends Job> jobClass){
        JobDataMap jobDataMap = new JobDataMap();
        Optional.ofNullable(params).ifPresent(jobDataMap::putAll);


        return JobBuilder.newJob(jobClass)
                .withIdentity(name, group)
                .setJobData(jobDataMap)
                .build();
    }

    public static void validateCron(String cronStr){
        if (StrUtil.isBlank(cronStr) || !CronExpression.isValidExpression(cronStr)) {
            throw new RuntimeException("CRON表达式不符合规范");
        }
    }
}
